/*

    This file is part of Blue Violin.

    Blue Violin is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Blue Violin is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero Public License for more details.

    You should have received a copy of the GNU Affero Public License
    along with Blue Violin.  If not, see <http://www.gnu.org/licenses/>.

    Blue Violin  Copyright (C) 2008  Blue Violin, Inc. & Josh Watts <josh.watts@blueviolin.org>
	For more information, visit http://www.blueviolin.org/

    This program comes with ABSOLUTELY NO WARRANTY.

*/

function BVAppEvents(sBrowser)
{
	this.objBrowser = document.getElementById(sBrowser);
	this.m_nActivePopup = 0;
	this.m_nID = Math.round(Math.random * 10000);
	this.m_objActiveBrowser = null;
	this.m_objPopup = null;
	this.m_aKeyPress = new Object();
	this.m_aKeyPressXml = {};
	
	this.m_bIgnoreEvents = false;
	this.m_bReplay = false;
	this.reRatchet = /RatchetBrowser\.dll/i;
	this.m_nBack = 0;
	this.m_nForward = 0;
	this.m_dtStart = null;
	this.m_oCurrentDocumentSelect = null;
	this.m_oCurrentDocumentSelectXml = null;

	this.ignoreWelcomeMessage = false;

	this.m_oBrowserEvents = $get(sBrowser);
	this.m_oBrowserEvents.attachEvent("TitleChange", $createDelegate(this, this.TitleChange));
	this.m_oBrowserEvents.attachEvent("StatusTextChange", $createDelegate(this, this.StatusTextChange));
	this.m_oBrowserEvents.attachEvent("NavigateComplete2", $createDelegate(this, this.NavigateComplete));
	this.m_oBrowserEvents.attachEvent("DocumentComplete", $createDelegate(this, this.DocumentComplete));
	this.m_oBrowserEvents.attachEvent("ElementOnClick", $createDelegate(this, this.ElementOnClick));
	this.m_oBrowserEvents.attachEvent("SelectOnChange", $createDelegate(this, this.SelectOnChange));
	this.m_oBrowserEvents.attachEvent("InputFileOnChange", $createDelegate(this, this.InputFileOnChange));
	this.m_oBrowserEvents.attachEvent("GetNewWindow", $createDelegate(this, this.GetNewWindow));
	this.m_oBrowserEvents.attachEvent("WindowClosing", $createDelegate(this, this.CloseWindow));
	this.m_oBrowserEvents.attachEvent("KeyPress", $createDelegate(this, this.KeyPress));
	this.m_oBrowserEvents.attachEvent("KeyDown", $createDelegate(this, this.KeyDown));
	this.m_oBrowserEvents.attachEvent("CommandStateChange", $createDelegate(this, this.CommandStateChange));
	this.m_oBrowserEvents.attachEvent("DocumentStart", $createDelegate(this, this.DocumentStart));
	this.m_oBrowserEvents.attachEvent("DocumentSelect", $createDelegate(this, this.DocumentSelect));
}

BVAppEvents.prototype.TitleChange = function(strTitle)
{
	if (-1 == strTitle.search(this.reRatchet))
	{
		document.title = "Blue Violin - " + strTitle;			
		// this.m_bIgnoreEvents = (false == this.m_bReplay) ? false : true;
	}
	else
	{
		if (false == this.ignoreWelcomeMessage)
		{
			document.title = "Blue Violin - Welcome to Blue Violin";
			// $get("txtToolbarAddress").value = "Welcome to Blue Violin";
			// // this.m_bIgnoreEvents = (false == this.m_bReplay) ? false : true;
			// this.m_bIgnoreEvents = true;
		}
	}
};


BVAppEvents.prototype.StatusTextChange = function(strText)
{
	window.status = strText;
};


BVAppEvents.prototype.NavigateComplete = function(strURL)
{
	if (-1 == strURL.search(this.reRatchet))
	{
		document.getElementById("txtToolbarAddress").value = strURL;
		// this.m_bIgnoreEvents = (false == this.m_bReplay) ? false : true;
	}
	else
	{
		if (false == this.ignoreWelcomeMessage)
		{
			// $get("txtToolbarAddress").value = "Welcome to Blue Violin";
			// this.m_bIgnoreEvents = true;
		}
	}
};


BVAppEvents.prototype.FormOnSubmit = function(oElement, oEvent)
{
	// objElement.bvAction = objElement.tagName;
	// var aAttributes = this.GetAttributes(oElement, oEvent);
	// this.AddAction("onchange", aAttributes);
	return;
};


BVAppEvents.prototype.SelectOnChange = function(oElement, oEvent)
{
	var aAttributes = this.GetAttributes(oElement, oEvent);
	this.AddAction("change", aAttributes);
};


BVAppEvents.prototype.InputFileOnChange = function(oElement, oEvent)
{

	var aAttributes = this.GetAttributes(oElement, oEvent);
	this.AddAction("change", aAttributes);
};


BVAppEvents.prototype.KeyPress = function(elemSrc, evEvent)
{
	var key;
	var bFlag = false;
	//alert(evEvent.keyCode);
	var aAttributes = this.GetAttributes(elemSrc, evEvent);
	if (false == this.m_bIgnoreEvents &&
		false == window.g_bIgnoreEvents)
	{
		this.AddAction("keypress", aAttributes);
	}
	return;
};


BVAppEvents.prototype.KeyDown = function(oSrc, oEvent)
{
	var oAttributes = null;

	if (false != this.m_bIgnoreEvents &&
		false != window.g_bIgnoreEvents)
	{
		return;
	}

	if (0x08 == oEvent.keyCode ||
		0x16 == oEvent.keyCode)
	{
		oAttributes = this.GetAttributes(oSrc, oEvent);
		this.AddAction("keypress", oAttributes);
		return;
	}

	if (0x20 <= oEvent.keyCode)
	{
		if (true == oEvent.ctrlKey)
		{
			oAttributes = this.GetAttributes(oSrc, oEvent);
			this.AddAction("keydown", oAttributes);

		}
	}


	return;		
};


BVAppEvents.prototype.ElementOnClick = function(oElement, oEvent)
{
	var aAttributes = this.GetAttributes(oElement, oEvent);
	// aAttributes["docPath"] = GetDocPath(oElement);
	if (false == this.m_bIgnoreEvents)
	{
		if (true == oEvent.ctrlKey &&
			2 == oEvent.button)
		{
			this.AddAction("elementcheckpoint", aAttributes);
		}
		else
		{
			this.AddAction("click", aAttributes);
		}
	}
	return;
};



BVAppEvents.prototype.DocumentStart = function(oDocument, sURL)
{
// 		if (false == me.m_bIgnoreEvents &&
// 			false == window.g_bIgnoreEvents)
// 		{
// 	if (null == this.m_dtStart)
// 	{
		this.m_dtStart = new Date();
// 	}
// 		}
};

BVAppEvents.prototype.DocumentComplete = function(strBrowserID, sURL)
{
	if (false == this.m_bIgnoreEvents &&
		false == window.g_bIgnoreEvents &&
		null != this.m_dtStart)
	{
		var aAttributes = new Object();
		var dtNow = new Date();
		var dtElapsed = new Date(dtNow.valueOf() - this.m_dtStart.valueOf());
		aAttributes["URL"] = sURL;
		aAttributes["Elapsed"] = dtElapsed;
		this.AddReportMessages(aAttributes);
		this.AddAction("documentcomplete", aAttributes);
		// wipe out all of the nodes we're holding for keypress events
		this.m_aKeyPress = new Object();

	}
};



BVAppEvents.prototype.GetNewWindow = function(strBrowserID)
{
	var divIEBrowser;
	var divPopup;
	var objIDispatch;
	var spnPopup;
	var spnInner;
	var imgClose;
	var aAttributes;
		
	divIEBrowser = document.getElementById("divMainBrowser");
	this.m_objActiveBrowser = document.getElementById(strBrowserID);
	divIEBrowser.style.zIndex = "-1";
	this.m_nActivePopup = ++window.nNextPopup;

	divPopup = $create("DIV");
	divPopup.id = "divPopup" + this.m_nActivePopup;
	divPopup.className = "Popup";
	divPopup.style.top = this.GetAbsoluteTop(divIEBrowser) + "px";
	divPopup.style.left = this.GetAbsoluteLeft(divIEBrowser) + "px";

	this.objPopup = $create("OBJECT");
	this.objPopup.classid = "clsid:B8C1C27C-E637-422A-A2DA-05176750AEBE";
	this.objPopup.id = "objPopup" + this.m_nActivePopup;
	this.objPopup.BrowserID = "objPopup" + this.m_nActivePopup;

	this.objPopup.style.height = $get("objMainBrowser").clientHeight;
	this.objPopup.style.width = $get("objMainBrowser").clientWidth;
	document.getElementById("spnBrowsers").appendChild(divPopup);
	divPopup.appendChild(this.objPopup);

// 	spnPopup = $create("SPAN");
// 	imgClose = $create("IMG");
// 	imgClose.src = "./images/toolbar/close_red_12_normal.gif";
// 	imgClose.style.height = "12px";
// 	imgClose.style.width = "12px";
// 	imgClose.id = "imgCloseSpnPopup" + this.m_nActivePopup;
// 	imgClose.className = "PopupTabClose";
	


// 	spnInner = $create("SPAN");
// 	spnInner.innerText = "Popup " + this.m_nActivePopup;
// 	spnPopup.appendChild(imgClose);
// 	spnPopup.appendChild(spnInner);
// 	window.oPopupTabs.addTab(spnPopup);
		
		
// 	spnPopup.id = "spnPopup" + this.m_nActivePopup;
// 	spnPopup.className= "PopupTabsSpan";
// 	document.getElementById("divPopupTabs").appendChild(spnPopup);

	var spnTab = window.oPopupTabs.addTab("Popup " + this.m_nActivePopup);

	window.oBrowsers["objPopup" + this.m_nActivePopup] = this.objPopup;
	window.oPopupScripts["objPopup" + this.m_nActivePopup] = new BVAppEvents("objPopup" + this.m_nActivePopup);

	objIDispatch = this.objPopup.BrowserIDispatch;
	this.m_objActiveBrowser.PopupIDispatch = objIDispatch;

	if (false == this.m_bIgnoreEvents &&
		false == window.g_bIgnoreEvents)
	{
		aAttributes = new Object();
		aAttributes["browser"] = "objPopup" + this.m_nActivePopup;

		this.SwitchActiveBrowser(spnTab);
	}

	window.objActiveBrowser = this.objPopup;
// http://samie.sourceforge.net/popupframes/basepage.html
};

BVAppEvents.prototype.CloseWindow = function(sBrowserID)
{
	var sTempID = sBrowserID.replace("obj", "");

	document.getElementById("obj" + sTempID).removeNode(false);
	document.getElementById("div" + sTempID).removeNode(false);
	document.getElementById("spn" + sTempID).removeNode(true);
	delete window.oBrowsers[sBrowserID];
	delete window.oPopupScripts[sTempID];
	this.SwitchActiveBrowser($get("spnMainBrowser"));
		
};



BVAppEvents.prototype.DocumentSelect = function(sHighlightedText, oRootElement)
{
	aAttributes = {};
	aAttributes["highlightedText"] = sHighlightedText;
	aAttributes["docPath"] = this.GetDocPath(oRootElement);
	aAttributes["tagName"] = oRootElement.tagName;
	aAttributes["id"] = oRootElement.id;
	aAttributes["name"] = oRootElement.name;
	aAttributes["delay"] = 0;
	aAttributes["retry"] = 0;
	this.AddReportMessages(aAttributes);
	this.AddAction("documentselect", aAttributes);
};



BVAppEvents.prototype.GetDocPath = function(oElement)
{
	var docRoot;
	var winChild;
	var winParent;
	var sDocPath = "document";

	winChild = oElement.document.parentWindow;

	while (true)
	{
		winParent = winChild.parent;
		// if winParent and winChild are equal, they're the same window
		// and we can't go any higher - bail out
		if (winParent == winChild)
		{
			break;
		}
		else
		{
			for (var i = 0;
				 i < winParent.frames.length;
				 ++i)
			{
				if (winChild == winParent.frames[i])
				{
					sDocPath = i + "::" + sDocPath;
					break;
				}
			}
			winChild = winParent;
			winParent = null;
		}
	}
	return sDocPath;
};


BVAppEvents.prototype.AddReportMessages = function(oAttributes)
{
	oAttributes.failedMessage = "";
	oAttributes.passedMessage = "";
};


BVAppEvents.prototype.GetAttributes = function(elemSrc, evEvent)
{

	var aAttributes = {};
	// common attributes
	aAttributes["id"] = elemSrc.id;
	aAttributes["name"] = elemSrc.name;
	aAttributes["sourceIndex"] = elemSrc.sourceIndex;
	aAttributes["tagName"] = elemSrc.tagName;
	aAttributes["event_type"] = evEvent.type;
	aAttributes["docPath"] = this.GetDocPath(elemSrc);
	aAttributes["delay"] = 0;
	aAttributes["retry"] = 0;

	this.AddReportMessages(aAttributes);

	// specific event attributes
	switch (evEvent.type.toUpperCase())
	{
		case "KEYPRESS":
		case "KEYDOWN":
			aAttributes["keyCode"] = evEvent.keyCode;
			aAttributes["altKey"] = evEvent.altKey;
			aAttributes["ctrlKey"] = evEvent.ctrlKey;
			aAttributes["shiftKey"] = evEvent.shiftKey;
			aAttributes["repeat"] = evEvent.repeat;
			break;

		case "MOUSEDOWN":
		case "MOUSEUP":
		case "CLICK":
			aAttributes["button"] = evEvent.button;				
			// aAttributes["clientX"] = evEvent.clientX;
			// aAttributes["clientY"] = evEvent.clientY;
			// aAttributes["offsetX"] = evEvent.offsetX;
			// aAttributes["offsetY"] = evEvent.offsetY;
			// aAttributes["screenX"] = evEvent.screenX;
			// aAttributes["screenY"] = evEvent.screenY;
			// aAttributes["x"] = evEvent.x;
			// aAttributes["y"] = evEvent.y;
			break;
	}
		
	// specific attributes
	switch (elemSrc.tagName.toUpperCase())
	{
		case "A":
			aAttributes["href"] = elemSrc.href;
			aAttributes["innerText"] = elemSrc.innerText;
			break;

		case "BODY":
			aAttributes["contentEditable"] = Boolean(elemSrc.contentEditable);
			break;

		case "B":
		case "I":
		case "EM":
			// var oParent = elemSrc.parentElement;
			elemParent = elemSrc.parentElement;
			aAttributes = this.GetAttributes(elemParent, evEvent);
			break;

		case "BUTTON":
			aAttributes["value"] = elemSrc.value;
			break;

		case "DIV":
			aAttributes["contentEditable"] = Boolean(elemSrc.contentEditable);
			aAttributes["innerText"] = elemSrc.innerText;
			break;

		case "FONT":
			elemParent = elemSrc.parentElement;
			aAttributes = this.GetAttributes(elemParent, evEvent);
			break;

		case "IMG":
			aAttributes["src"] = elemSrc.src;
			aAttributes["title"] = elemSrc.title;
			break;

		case "INPUT":
			aAttributes["type"] = elemSrc.type;
			switch (elemSrc.type.toUpperCase())
			{
				case "BUTTON":
					aAttributes["value"] = elemSrc.value;
					break;

				case "FILE":
					aAttributes["value"] = elemSrc.value;
					break;
						
						
				case "CHECKBOX":
					aAttributes["value"] = elemSrc.value;
					aAttributes["checked"] = elemSrc.checked;
					aAttributes["disabled"] = elemSrc.disabled;
					break;

				case "RADIO":
					aAttributes["value"] = elemSrc.value;
					break;

				case "SUBMIT":
					aAttributes["value"] = elemSrc.value;
					break;

				case "TEXT":
					aAttributes["value"] = elemSrc.value;
					break;
						
				default:
					aAttributes["value"] = elemSrc.value;
					break;
			}
			break;

		case "SELECT":
			aAttributes["selectedIndex"] = elemSrc.selectedIndex;
			aAttributes["value"] = elemSrc.value;
			break;

		case "SPAN":
			aAttributes["innerText"] = elemSrc.innerText;
			aAttributes["title"] = elemSrc.title;
			break;

		case "STRONG":
			aAttributes = this.GetAttributes(elemSrc.parentElement, evEvent);
			break;
				
		case "TEXTAREA":
			aAttributes["value"] = elemSrc.value;
			break;

		case "TD":
			aAttributes["cellSpan"] = elemSrc.cellSpan;
			aAttributes["rowSpan"] = elemSrc.rowSpan;
			aAttributes["innerText"] = elemSrc.innerText;
			break;
	}
	return aAttributes;
};


BVAppEvents.prototype.AddAction = function(sAction, aAttributes)
{
	var oTree = null;
	var oNode = null;
	var oLabel = null;
	var oTempNode = null;
	var oSubTree = null;
	var oSubNode = null;
	var sLabel = "";
	var sLabelAction = "";
	var sLabelDesc = "";
	
	var sTitle = "";
	var sKey = "";
	var sNodeImage = "";
	var bAppendNode = true;
	var xmlNode = null;
	var xmlAttribute = null;
	var oTemp = null;
	var aKeyPressCodes = null;
	
	xmlNode = this.m_xmlEvents.createNode(1, sAction, "");
	// reset the DocumentSelect node if it isn't a 
	// 'documentselect' action
	this.m_oCurrentDocumentSelect = ("documentselect" == sAction) ? this.m_oCurrentDocumentSelect : null ;
	switch (sAction)
	{
		case "back":
			sLabelAction = "Back";
			sTitle = "Back";
			sNodeImage = "back_16_normal.gif";
			break;


		case "change":
			switch (aAttributes["tagName"].toUpperCase())
			{
				case "INPUT":
					switch (aAttributes["type"].toUpperCase())
					{
						case "FILE":
							sLabelAction = "File";
							sLabelDesc = aAttributes["value"];
							sTitle = "File: " + aAttributes["value"];
							sNodeImage = "changefile_16_normal.gif";
							break;
					}
					break;
			
			
				case "SELECT":
					sLabelAction = "Select (change)";
					sLabelDesc = aAttributes["id"];
					sTitle = "You selected \"" + aAttributes["id"] + "\"";
					sNodeImage = "selectchoose_16_normal.gif";
					break;
			
			}
			break;


		case "changebrowser":
			// sLabel = "Changed Browser = " + aAttributes["browser"];
			sLabelAction = "Switch Browser";
			sLabelDesc =  aAttributes.browser;
			sNodeImage = "changebrowser_16_normal.gif";
			break;


		case "click":
			sNodeImage = "click_16_normal.gif";
			switch (aAttributes["tagName"].toUpperCase())
			{
				case "A":
					sLabelAction = "Link";
					sLabelDesc = aAttributes.innerText.nbsp();
					sTitle = "You clicked the link \"" + aAttributes["innerText"] + "\"";
					sNodeImage = "clicklink_16_normal.gif";
					break;


				case "BUTTON":
					sLabelAction = "Button";
					sLabelDesc = aAttributes.value;
					sTitle = "You clicked the button \"" + aAttributes["value"] + "\"";
					sNodeImage = "clickbutton_16_normal.gif";
					break;

			
				case "IMG":
					// sLabel = "Image = " + aAttributes["src"];
					sLabelAction = "Image";
					if (null != aAttributes.id)
					{
						sLabelDesc = aAttributes.id + "&nbsp;(" + aAttributes.id + ")";
					}
					else
					{
						sLabelDesc = aAttributes.src;
					}
					sTitle = "You clicked on image \"" + aAttributes.src + "\"";
					sNodeImage = "clickimage_16_normal.gif";
					break;


				case "INPUT":
					switch (aAttributes["type"].toUpperCase())
					{
						case "BUTTON":
							sLabelAction = "Button";
							sLabelDesc = aAttributes.value;
							sTitle = "You clicked the button \"" + aAttributes["value"] + "\"";
							sNodeImage = "clickbutton_16_normal.gif";
							break;


						case "FILE":
							// we don't want to process a click on an input file element
							return;


						case "CHECKBOX":
							sLabelAction = "Checkbox";
							sLabelDesc = aAttributes.name;
							sTitle = "You clicked on the checkbox \"" + aAttributes["name"] + "\"";
							sNodeImage = "clickcheckbox_16_normal.gif";
							break;


						case "IMAGE":
							sLabelAction = "Image";
							sLabelDesc = aAttributes.src;
							sTitle = "You clicked on image \"" + aAttributes["src"] + "\"";
							sNodeImage = "clickimage_16_normal.gif";
							break;


						case "RADIO":
							sLabelAction = "Radio";
							sLabelDesc = aAttributes.name;
							sTitle = "You clicked on the radio button \"" + aAttributes["name"] + "\"";
							sNodeImage = "clickradio_16_normal.gif";
							break;


						case "SUBMIT":
							sLabelAction = "Button";
							sLabelDesc = aAttributes.value.nbsp();
							sTitle = "You clicked the button \"" + aAttributes["value"] + "\"";
							sNodeImage = "clickbutton_16_normal.gif";
							break;

				
						default:
							sLabelAction = "Input";
							sLabelDesc = aAttributes.name;
							sTitle = "You clicked on input \"" + aAttributes["name"] + "\"";
							break;
					}
					break;

				case "SELECT":
					sLabelAction = "Select";
					sLabelDesc = aAttributes.id;
					sTitle = "You clicked on select box \"" + aAttributes["id"] + "\"";
					sNodeImage = "clickselect_16_normal.gif";
					break;

				case "SPAN":
					sLabelAction = "Span";
					sLabelDesc = aAttributes.innerText;
					sTitle = "You clicked on span \"" + aAttributes["innerText"] + "\"";
					break;

				default:
					sLabelAction = aAttributes.tagName;
					sTitle = "You clicked on " + aAttributes.tagName;
					if (null != aAttributes.id &&
						"" != aAttributes.id)
					{
						sLabelAction += "&nbsp;(" + aAttributes.id + ")";
					}
					break;
			
			}
			break;


		case "closewindow":
			sLabelAction = "Close Browser".nbsp();
			sTitle = "Close Browser";			
			sNodeImage = "closebrowser_16_normal.gif";
			break;


		case "documentcomplete":
			if (null != aAttributes["Elapsed"])
			{
				if ("string" != typeof(aAttributes["Elapsed"]))
				{
					aAttributes["Elapsed"] = aAttributes["Elapsed"].format();
				}
				sLabel = "Document Complete - " + aAttributes["Elapsed"];
			
			}
			else
			{
				sLabel = "Document Complete";
			}

			sLabelAction = "Document Complete";
			sLabelDesc = (null != aAttributes["Elapsed"]) ? aAttributes["Elapsed"] : "";


			sTitle = "Document Complete";
			sNodeImage = "documentcomplete_16_normal.gif";
			break;


		case "documentselect":
			sLabelAction = "Text&nbsp;Checkpoint";
			sLabelDesc = aAttributes.highlightedText.nbsp();
			sTitle = "Text checkpoint for " + aAttributes["highlightedText"];
			sNodeImage = "documentselect_16_normal.gif";
			if (null == this.m_oCurrentDocumentSelect)
			{
				oNode = createNode();
				this.m_oCurrentDocumentSelect = oNode;
				this.m_oCurrentDocumentSelectXml = xmlNode;
			}
			else
			{
				oNode = this.m_oCurrentDocumentSelect;
				xmlNode = this.m_oCurrentDocumentSelectXml;
				//oNode.prop_highlightedText.innerHTML = "highlightedText - " + aAttributes["highlightedText"];
				oNode.prop_highlightedText.childNodes[1].data = aAttributes.highlightedText;
				xmlNode.setAttribute("highlightedText", aAttributes["highlightedText"]);
				bAppendNode = false;
			}
			break;

		case "elementcheckpoint":
			sLabelAction = "Element Checkpoint";
			sTitle = "Element Checkpoint";
			sNodeImage = "elementcheckpoint_16_normal.gif";
			break;
			



		case "forward":
			sLabelAction = "Forward";
			sTitle = "Forward";
			sNodeImage = "forward_16_normal.gif";
			break;


		case "home":
			sLabelAction = "Home";
			sTitle = "Home";
			sNodeImage = "home_16_normal.gif";
			break;

		case "keydown":
			sLabelAction = "Key&nbsp;Down";
			if (true == aAttributes.ctrlKey)
			{
				sLabelDesc += "Ctrl+";
			}
			sLabelDesc += String.fromCharCode(aAttributes.keyCode);
			sNodeImage = "keydown_16_normal.gif";
			break;
			


		case "keypress":
			var key;
			var bFlag = false;
			sNodeImage = "keypress_16_normal.gif";

			// try to match the previous keypress node
			// with the current keypress source node
			for (key in this.m_aKeyPress)
			{
				if (key == aAttributes["name"] ||
					key == aAttributes["id"])
				{

					// found it
					var sText;
					if (true == this.isContentEditable(aAttributes))
					{
						sText = aAttributes["innerText"];
						oTemp = aAttributes["innerText"] + String.fromCharCode(aAttributes["keyCode"]);
					}
					else
					{
						sText = aAttributes["value"];
						oTemp = aAttributes["value"] + String.fromCharCode(aAttributes["keyCode"]);
					}
					oNode = this.m_aKeyPress[key];
					xmlNode = this.m_aKeyPressXml[key];

					aKeyPressCodes = xmlNode.getAttribute("keyCodeArray");
					aKeyPressCodes += "," + aAttributes.keyCode;
					xmlNode.setAttribute("keyCodeArray", aKeyPressCodes);

					
					//oTemp = sText + String.fromCharCode(aAttributes.keyCode);

					//oNode.prop_value.innerHTML = "value - " +  oTemp;
					xmlNode.setAttribute("value", oTemp);
					xmlNode.setAttribute("keyCode", aAttributes["keyCode"]);
					sLabelAction = "Key&nbsp;Press";
					switch (aAttributes["keyCode"])
					{
						case 8:
							sLabelDesc = sText.substr(0, aAttributes["value"].length - 1).nbsp();
							break;
							
						case 13:
							sLabelDesc = (sText + "[ENTER]").nbsp();
							break;
							
						default:
							sLabelDesc = (sText + String.fromCharCode(aAttributes["keyCode"])).nbsp();
							break;
					}

					bFlag = true;
					bAppendNode = false;
					break;
				}
			}
			if (false == bFlag)
			{
				// couldn't match the current keypress node
				sLabelAction = "Key&nbsp;Press";
				if ("" == aAttributes["value"] ||
					"undefined" == typeof(aAttributes.value))
				{
					sLabelDesc = String.fromCharCode(aAttributes.keyCode);
					sTitle = "You pressed key \"" + String.fromCharCode(aAttributes["keyCode"]) + "\"";
				}
				else
				{
					sLabelDesc = aAttributes.value.replace(/\s/g, "&nbsp;");
					sTitle = "You typed \"" + aAttributes["value"] + "\"";
				}
				oNode = createNode();

				xmlNode.setAttribute("keyCodeArray", aAttributes.keyCode);
				
				bIdentified = (undefined != aAttributes["name"]) || (undefined != aAttributes["id"]);
				bTag = ("INPUT" == aAttributes["tagName"]) || ("TEXTAREA" == aAttributes["tagName"]);
				bContentEditable = this.isContentEditable(aAttributes);
				if (bIdentified &&
					(bTag || bContentEditable))
				{
					if (undefined == aAttributes["name"])
					{
						this.m_aKeyPress[aAttributes["id"]] = oNode;
						this.m_aKeyPressXml[aAttributes["id"]] = xmlNode;
					}					

					else
					{
						this.m_aKeyPress[aAttributes["name"]] = oNode;
						this.m_aKeyPressXml[aAttributes["name"]] = xmlNode;
					}
				
				}
				
			}
			break;

		case "newpopupbrowser":
			sLabelAction = "Popup" ;
			sTitle = "";
			sNodeImage = "newpopupbrowser_16_normal.gif";
			break;

		case "navigate":
			sLabelAction = "Navigate";
			sLabelDesc = aAttributes["URL"];
			sTitle = "You went to " + aAttributes["URL"];
			sNodeImage = "navigate_16_normal.gif";
			break;
	}
	// add action to the tree
	if (null == oNode)
	{
		oNode = createNode();
	}

	oTree = document.getElementById("ulTree");
	if (null != oTree)
	{		
		oNode.label.innerHTML = "<img src=\"./images/actiontree/" + sNodeImage + "\" class=\"ActionNodeImage\" />" +
			"<b>" + sLabelAction + "</b>";
		if ("" != sLabelDesc)
		{
			oNode.label.innerHTML += "&nbsp;::&nbsp;" + sLabelDesc;
		}
		
		
		oNode.title = sTitle;


		oSubTree = document.createElement("UL");
		oSubTree.className = "ActionSubTree";
		// add event to attributes
		oSubNode = document.createElement("LI");
		oSubNode.innerHTML = "<b name=\"true\">action</b> " + sAction;
		oSubTree.appendChild(oSubNode);
		
		if (true == bAppendNode)
		{
			oNode.className = "ActionNode";
			window.oActionTree.addNode(oNode, sAction);
			oTree.appendChild(oNode);
			for (sKey in aAttributes)
			{
				if (Object.toJSONString === aAttributes[sKey])
				{
					continue;
				}
				oSubNode = document.createElement("LI");
				oSubNode.innerHTML = "<b name=\"true\">" + sKey + "</b> ";
				if ("undefined" != typeof aAttributes[sKey])
				{
					oSubNode.innerHTML += aAttributes[sKey].toString().nbsp();
				}
				oSubNode.title = aAttributes[sKey];
				oSubNode.unselectable = true;
				oSubTree.appendChild(oSubNode);
				// set node properties directly to the display 
				oNode["prop_" + sKey] = oSubNode;
				
				// XML action items
				xmlNode.setAttribute(sKey, aAttributes[sKey]);
			}
			this.m_xmlEvents.documentElement.appendChild(xmlNode);
		}
		oSubTree.style.display = "none";
		oNode.appendChild(oSubTree);
		oNode.unselectable = "on";
		oNode.scrollIntoView(false);
		// oSubNode.scrollIntoView(false);
	}


	function createNode()
	{
		var oTempNode = null;
		var oTempLabel = null;
		oTempNode = $create("LI");
		oTempLabel = $create("SPAN");
		oTempLabel.id = "spnLabel";
		oTempNode.appendChild(oTempLabel);
		oTempNode.label = oTempLabel;
		return oTempNode;
	};

};


BVAppEvents.prototype.isContentEditable = function(aAttributes)	
{
	var bReturn;
	if (("DIV" == aAttributes["tagName"]) && (true == aAttributes["contentEditable"]))
	{
		bReturn = true;
	}
	else
	{
		bReturn = false;
	}
	return bReturn;
};



//
// toolbar support functions
BVAppEvents.prototype.Back = function()
{
	if (false == this.m_bIgnoreEvents)
	{
		this.AddAction("back", null);
	}
};

		
BVAppEvents.prototype.Forward = function()
{
	if (false == this.m_bIgnoreEvents)
	{
		this.AddAction("forward", null);
	}
};


BVAppEvents.prototype.Home = function()
{
	if (false == this.m_bIgnoreEvents)
	{
		this.AddAction("home", null);
	}
};


// support functions
//
BVAppEvents.prototype.AddNavigate = function(sURL)
{
	if (false == this.m_bIgnoreEvents)
	{
		var aAttributes = {};
		aAttributes["URL"] = sURL;
		this.AddReportMessages(aAttributes);
		this.AddAction("navigate", aAttributes);
	}
};


BVAppEvents.prototype.ClearEvents = function()
{
	var oTree = document.getElementById("ulTree");
	oTree.innerHTML = "";

	this.ClearPopups();
	window.nNextPopup = 0;
	window.oActionTree.reset();

	this.m_xmlEvents.loadXML("<script></script>");	
	return;
};


BVAppEvents.prototype.ClearPopups = function()
{
	var aChildren = $get("divPopupTabs").children
	var nChildren = aChildren.length;
	var rePopup = /popup/i;
	var t_IgnoreEvents = this.m_bIgnoreEvents;
	var t_g_bIgnoreEvents = window.g_bIgnoreEvents;


	this.m_bIgnoreEvents = true;
	window.g_bIgnoreEvents = true;

	for (var i = 0;
		 i < nChildren;
		 ++i)
	{
		spnChild = aChildren.item(aChildren.length - 1);
		if (-1 != spnChild.id.search(rePopup))
		{
			this.CloseWindow(spnChild.id.replace("spn", "obj"));
		}
	}

	this.m_bIgnoreEvents = t_IgnoreEvents;
	window.g_bIgnoreEvents = t_g_bIgnoreEvents;

	window.oPopupTabs.reset();

};


BVAppEvents.prototype.GetXML = function()
{
	return this.m_xmlEvents.xml;
};


BVAppEvents.prototype.get_xmlEvents = function()
{
	return this.m_xmlEvents;
};


BVAppEvents.prototype.PrepareReplay = function()
{
	// var objIEBrowser = document.getElementById("objIEBrowser");
	window.nNextPopup = 0;
	// this.m_nNextPopup = 0;
	window.g_bIgnoreEvents = true;
		
	this.m_bIgnoreEvents = true;
	this.m_bReplay = true;
	this.objBrowser.ignoreEvents = true;
	return this.m_xmlEvents;
};


BVAppEvents.prototype.pause = function()
{
	window.g_bIgnoreEvents = true;
	this.m_bIgnoreEvents = true;
	this.objBrowser.ignoreEvents = true;
};

BVAppEvents.prototype.record = function()
{
	window.g_bIgnoreEvents = false;
	this.m_bIgnoreEvents = false;
	this.objBrowser.ignoreEvents = false;
};


BVAppEvents.prototype.FinishReplay = function()
{
	// var objIEBrowser = document.getElementById("objIEBrowser");
	window.g_bIgnoreEvents = false;
		
	this.m_bIgnoreEvents = false;
	this.m_bReplay = false;
	this.objBrowser.ignoreEvents = false;
	return;
};


//
// file support methods
BVAppEvents.prototype.LoadScript = function(sScript)
{
	var xmlNodeList;
	var xmlScript = new ActiveXObject("Msxml2.DOMDocument");
	this.ClearEvents();
	xmlScript.loadXML(sScript);
		
	xmlNodeList = xmlScript.documentElement.childNodes;
	for (var i = 0;
		 i < xmlNodeList.length;
		 ++i)
	{
		var xmlNode = xmlNodeList.item(i);
		var xmlAttributes = xmlNode.attributes;
		var aAttributes = new Object;
		for (var j = 0;
			 j < xmlAttributes.length;
			 ++j)
		{
			aAttributes[xmlAttributes.item(j).nodeName] = xmlAttributes.item(j).value;
		}
		this.AddAction(xmlNode.nodeName, aAttributes);
	}
	delete xmlScript;
};



BVAppEvents.prototype.OpenScript = function(sScriptName)
{
	var xmlRoot;
	var oXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
	oXMLHTTP.open("GET", 
				  "scripts.php?action=load&name=" + encodeURIComponent(sScriptName),
				  false);
	oXMLHTTP.send();
	xmlRoot = oXMLHTTP.responseXML;
	// alert(xmlRoot.documentElement.firstChild.text);
	this.LoadScript(xmlRoot.documentElement.firstChild.text);
};


BVAppEvents.prototype.SaveScript = function(sScriptName)
{
// 	var oXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
	// alert(encodeURIComponent(this.m_xmlEvents.xml));
// 	var hr = oXMLHTTP.open("POST",
// 						   "scripts.php",
// 						   false,
// 						   null,
// 						   null);
// 	hr = oXMLHTTP.setRequestHeader("Content-Type",
// 								   "application/x-www-form-urlencoded");

	var oHttp = $http("POST", "scripts.php");
	hr  = oHttp.send("action=save&name=" + encodeURIComponent(sScriptName) +
			   "&script=" + encodeURIComponent(this.m_xmlEvents.xml));
	return;
};


//
// misc. support functions
// 		
BVAppEvents.prototype.GetAbsoluteTop = function(objElement)
{
	var nTotal = 0;
	if (null == objElement)
	{
		return 0;
	}
	nTotal = objElement.offsetTop + this.GetAbsoluteTop(objElement.offsetParent);
	return nTotal;
	// alert(objElement.offsetTop);
};


BVAppEvents.prototype.GetAbsoluteLeft = function(objElement)
{
	var nTotal = 0;
	if (null == objElement)
	{
		return 0;
	}
	nTotal = objElement.offsetLeft + this.GetAbsoluteLeft(objElement.offsetParent);
	return nTotal;
};


BVAppEvents.prototype.SwitchActiveBrowser = function(objElement)
{
	var sID = objElement.id;
	var divPopupTabs = document.getElementById("divPopupTabs");
	var aChildren = divPopupTabs.children;
	var spnChild;
	var aAttributes;

	for (var i = 0;
		 i < aChildren.length;
		 i++)
	{
		spnChild = aChildren.item(i);
		if (sID == spnChild.id)
		{
			aAttributes = {};
			aAttributes["browser"] = spnChild.id.replace("spn", "obj");
			this.AddReportMessages(aAttributes);
			if (false == this.m_bIgnoreEvents &&
				false == window.g_bIgnoreEvents)
			{
				this.AddAction("changebrowser", aAttributes);
			}
			$get(spnChild.id.replace("spn", "div")).style.zIndex = "100";
			$get(spnChild.id.replace("spn", "obj")).style.width = WindowResizer.get_browserWidth() + "px";
			$get(spnChild.id.replace("spn", "obj")).style.height = WindowResizer.get_browserHeight() + "px";
			window.objActiveBrowser = $get(spnChild.id.replace("spn", "obj"));
			this.TitleChange(window.objActiveBrowser.Document.title);
			$get("txtToolbarAddress").value = window.objActiveBrowser.Document.URL;
			window.oToolbar.CommandStateChange(1, this.m_nForward);
			window.oToolbar.CommandStateChange(2, this.m_nBackward);
		}
		else
		{
			$get(spnChild.id.replace("spn", "div")).style.zIndex = "-1";
			$get(spnChild.id.replace("spn", "obj")).style.height = "0px";
			$get(spnChild.id.replace("spn", "obj")).style.width = "0px";
		}
	}
};


BVAppEvents.prototype.CommandStateChange = function(nCommands, bEnabled)
{
	if (null != window.objActiveBrowser)
	{
		if (this.objBrowser.BrowserID == window.objActiveBrowser.BrowserID)
		{
			switch (nCommands)
			{
				case 1:
				this.m_nForward = bEnabled;
				break;
						
				case 2:
				this.m_nBack = bEnabled;
				break;
			}
			oToolbar.CommandStateChange(nCommands, bEnabled);
		}
	}
	return;
};


BVAppEvents.prototype.removeNode = function(nNode)
{
	var sXml;
	var aNodes = [];
	var oNode = this.m_xmlEvents.documentElement.childNodes.item(nNode);
	aNodes.push(oNode);
	if ("documentcomplete" == oNode.tagName.toLowerCase())
	{
		aNodes.push(oNode.previousSibling);
	}
	oNode = oNode.nextSibling;
	while (null != oNode && "documentcomplete" == oNode.tagName.toLowerCase())
	{
		aNodes.push(oNode);
		oNode = oNode.nextSibling;
	}

	for (i = 0;
		 i < aNodes.length;
		 ++i)
	{
		this.m_xmlEvents.documentElement.removeChild(aNodes[i]);
	}
	sXml = this.GetXML();
	this.ClearEvents();
	this.LoadScript(sXml);

};

BVAppEvents.prototype.m_xmlEvents = new ActiveXObject("Msxml2.DOMDocument");
BVAppEvents.prototype.m_xmlEvents.async = false;
BVAppEvents.prototype.m_xmlEvents.loadXML("<script></script>");
// window.g_bvPopupScripts = new Array();
